package queue;

import java.util.LinkedList;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @ClassName MyLinkedBlockingQueue
 * @Description
 * @Company inspur
 * @Author Kevin
 * @Date 2020/7/10 17:32
 * @Version 1.0
 */
public class MyLinkedBlockingQueue<E> {
    private final int capacity;
    private Lock lock = new ReentrantLock();
    private Condition notFull = lock.newCondition();
    private Condition notEmpty = lock.newCondition();
    private volatile int size;
    private LinkedList<E> queue;

    public MyLinkedBlockingQueue() {
        this(Integer.MAX_VALUE);
    }

    public MyLinkedBlockingQueue(int capacity) {
        this.capacity = capacity;
        queue = new LinkedList<E>();
    }

    public void put(E e) {
        lock.lock();
        try {
            while (size == capacity) {
                notFull.await();
            }
            queue.add(e);
            size++;
            notFull.signalAll();
        } catch (InterruptedException interruptedException) {
            interruptedException.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public E take() throws InterruptedException {
        lock.lock();
        try {
            while (size == 0) {//队列为空，阻塞
                notEmpty.await();
            }
            E e = queue.pop();
            size--;
            notFull.signal();
            return e;
        } finally {
            lock.unlock();
        }
    }

}
